package cpi.entity;

import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.*;
import org.springframework.util.ResourceUtils;
import org.xml.sax.SAXException;
import sun.java2d.pipe.SpanIterator;

import javax.xml.bind.JAXBException;
import java.io.*;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class PMMLDemo {
    public Evaluator loadPmml(String modelName) throws FileNotFoundException {
        PMML pmml = new PMML();
        File file = ResourceUtils.getFile("classpath:model/"+modelName);
        InputStream inputStream = null;

        try {
            inputStream = Files.newInputStream(file.toPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (inputStream == null) {
            return null;
        }
        InputStream is = inputStream;
        try {
            pmml = org.jpmml.model.PMMLUtil.unmarshal(is);
        } catch (SAXException e1) {
            e1.printStackTrace();
        } catch (JAXBException e1) {
            e1.printStackTrace();
        } finally {
            //关闭输入流
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory.newInstance();
        Evaluator evaluator = modelEvaluatorFactory.newModelEvaluator(pmml);
        pmml = null;
        return evaluator;
    }

    public Double predict(Evaluator evaluator, Map<String, Integer> featuremap) {
        Double result = 0.0;
        List<InputField> inputFields = evaluator.getInputFields();
        Map<FieldName, FieldValue> arguments = new LinkedHashMap<>();
        for (InputField inputField : inputFields) {
            FieldName inputFieldName = inputField.getName();
            Object rawValue = featuremap.get(inputFieldName.getValue());
            FieldValue inputFieldValue = inputField.prepare(rawValue);
            arguments.put(inputFieldName, inputFieldValue);
        }

        Map<FieldName, ?> results = evaluator.evaluate(arguments);
        List<TargetField> targetFields = evaluator.getTargetFields();

        TargetField targetField = targetFields.get(0);
        FieldName targetFieldName = targetField.getName();

        Object targetFieldValue = results.get(targetFieldName);
//        System.out.println("target: " + targetFieldName.getValue() + " value: " + targetFieldValue);
        int primitiveValue = -1;
        if (targetFieldValue instanceof Computable) {
            Computable computable = (Computable) targetFieldValue;
//            System.out.println(computable.getResult());
            return Double.valueOf(computable.getResult()+"");
//            return (Double) computable.getResult();
//            primitiveValue = (Integer) computable.getResult();
        }
        return (Double) targetFieldValue;
    }

    public static Map<String, Integer> converter(String type, String province, String representTime) {
        HashMap<String, Integer> typeMap = new HashMap<String, Integer>() {{
            put("居民消费价格指数", 1);
            put("食品烟酒类", 2);
            put("衣着类", 3);
            put("居住类", 4);
            put("生活用品及服务类", 5);
            put("交通和通信类", 6);
            put("教育文化和娱乐类", 7);
            put("医疗保健类", 8);
            put("其他用品和服务类", 9);
        }};
        HashMap<String, Integer> provinceMap = new HashMap<String, Integer>() {{
            put("全国", 1);
            put("北京市", 2);
            put("宁夏回族自治区", 3);
            put("青海省", 4);
            put("甘肃省", 5);
            put("陕西省", 6);
            put("西藏自治区", 7);
            put("云南省", 8);
            put("贵州省", 9);
            put("四川省", 10);
            put("重庆市", 11);
            put("海南省", 12);
            put("广西壮族自治区", 13);
            put("广东省", 14);
            put("湖南省", 15);
            put("湖北省", 16);
            put("河南省", 17);
            put("山东省", 18);
            put("江西省", 19);
            put("福建省", 20);
            put("安徽省", 21);
            put("浙江省", 22);
            put("江苏省", 23);
            put("上海市", 24);
            put("黑龙江省", 25);
            put("吉林省", 26);
            put("辽宁省", 27);
            put("内蒙古自治区", 28);
            put("山西省", 29);
            put("河北省", 30);
            put("天津市", 31);
            put("新疆维吾尔自治区", 32);
        }};
        HashMap<String, Integer> timeMap = new HashMap<String, Integer>() {{
            put("2020/6/1", 1);
            put("2020/7/1", 2);
            put("2020/8/1", 3);
            put("2020/9/1", 4);
            put("2020/10/1", 5);
            put("2020/11/1", 6);
            put("2020/12/1", 7);
            put("2021/1/1", 8);
            put("2021/2/1", 9);
            put("2021/3/1", 10);
            put("2021/4/1", 11);
            put("2021/5/1", 12);
            put("2021/6/1", 13);
            put("2021/7/1", 14);
            put("2021/8/1", 15);
            put("2021/9/1", 16);
            put("2021/10/1", 17);
            put("2021/11/1", 18);
            put("2021/12/1", 19);
            put("2022/1/1", 20);
            put("2022/2/1", 21);
            put("2022/3/1", 22);
            put("2022/4/1", 23);
            put("2022/5/1", 24);
            put("2022/6/1", 1);
            put("2022/7/1", 2);
            put("2022/8/1", 3);
            put("2022/9/1", 4);
            put("2022/10/1", 5);
            put("2022/11/1", 6);
            put("2022/12/1", 7);
            put("2023/1/1", 8);
            put("2023/2/1", 9);
            put("2023/3/1", 10);
            put("2023/4/1", 11);
            put("2023/5/1", 12);
            put("2023/6/1", 13);
            put("2023/7/1", 14);
            put("2023/8/1", 15);
            put("2023/9/1", 16);
            put("2023/10/1", 17);
            put("2023/11/1", 18);
            put("2023/12/1", 19);
        }};
//        PredictModel predictModel = new PredictModel();
//        predictModel.setType(typeMap.get(type));
//        predictModel.setProvince(provinceMap.get(province));
//        predictModel.setRepresentTime(timeMap.get(representTime));
        HashMap<String, Integer> data = new HashMap<String, Integer>() {{
            put("x1", typeMap.get(type));
            put("x2", provinceMap.get(province));
            put("x3", timeMap.get(representTime));
        }};
        return data;
    }
    public static String predictCpi(String modelName, String type, String province, String representTime) throws FileNotFoundException {
        PMMLDemo demo = new PMMLDemo();
        Evaluator model = demo.loadPmml(modelName+".pmml");
        Map<String, Integer> data = converter(type,province,representTime);
        return String.format("%.1f", demo.predict(model, data)/10);

    }
    public static void main(String args[]) throws Exception {
        System.out.println(predictCpi("xgboost","居民消费价格指数","全国","2023/1/1"));
        System.out.println(predictCpi("softmax_reg","居民消费价格指数","陕西省","2023/1/1"));
        System.out.println(predictCpi("poly_svm","居民消费价格指数","陕西省","2023/1/1"));
    }

}
